home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include <stdio.h>
-
- #include "symbol.h"
- #include "code.h"
- #include "math.tab.h"
- #include "fudgit.h"
- #include "setshow.h"
- #include "dalloca.h"
- #include "head.h"
-
- static void fft(double *data, int nn, int isign);
- static void merge(double *real, double *ima, double *comp, int nn);
- static void split(double *comp, double *real, double *ima, int nn);
- static int checkbit(unsigned int data);
- static int fftsmooth(double *fromvec, double *smvec, int ndata, float sigma);
-
- /* called with 4 arguments (argc=5) */
- int Ft_run_fft(int argc, char **argv, int dir, int ndata)
- {
- double *vectors[4], *complex;
- Symbol *sym;
- int i;
- extern Symbol *Ft_lookup(char *s), *Ft_install(char *s, int t, int size);
- int Ft_varcpy(char *to, char *from);
-
- if (ndata == 0) {
- fputs("(inv)fft: No data!\n", stderr);
- return(ERRR);
- }
- if (checkbit(ndata) != 1) {
- fputs("(inv)fft: Fast fourier transform requires 2^n data points.\n",
- stderr);
- return(ERRR);
- }
- ADVECTOR(complex, 1, 2*ndata, "(inv)fft", return);
- for (i=1; i<=4; i++) {
- if ((sym = Ft_lookup(argv[i])) == 0) { /* get all vectors */
- if (i<=2) {
- fprintf(stderr, "(inv)fft: %s: Unknown vector.\n", argv[i]);
- return(ERRR);
- }
- if (Ft_varcpy(NULL, argv[i]) != VEC) {
- fprintf(stderr,
- "(inv)fft: %s: Not a legal vector name.\n", argv[i]);
- return(ERRR);
- }
- sym = Ft_install(argv[i], VEC, Ft_Samples);
- }
- vectors[i-1] = sym->u.vec;
- }
- /* make it complex */
- merge(vectors[0], vectors[1], complex, ndata);
- fft(complex, ndata, dir); /* take the fourier transform */
- /* split in two vectors */
- split(complex, vectors[2], vectors[3], ndata);
- return(0);
- }
-
- /* called with 3 arguments (argc=4) */
- int Ft_run_smooth(int argc, char **argv, int ndata)
- {
- double *vectors[2];
- Symbol *sym;
- int i;
- float sigma;
- extern Symbol *Ft_lookup(char *s), *Ft_install(char *s, int t, int size);
- int Ft_varcpy(char *to, char *from);
-
- if (ndata == 0) {
- fputs("smooth: No data!\n", stderr);
- return(ERRR);
- }
- if (sscanf(argv[1], "%f", &sigma) != 1) {
- fputs("Error: smooth: Cannot read smoothing factor.\n", stderr);
- return(ERRR);
- }
- for (i=2; i<=3; i++) {
- if ((sym = Ft_lookup(argv[i])) == 0) { /* get all vectors */
- if (i==2) {
- fprintf(stderr,
- "Error: smooth: %s: Unknown vector.\n", argv[i]);
- return(ERRR);
- }
- if (Ft_varcpy(NULL, argv[i]) != VEC) {
- fprintf(stderr,
- "Error: smooth: %s: Not a legal vector name.\n", argv[i]);
- return(ERRR);
- }
- sym = Ft_install(argv[i], VEC, Ft_Samples);
- }
- vectors[i-2] = sym->u.vec;
- }
- return(fftsmooth(vectors[0], vectors[1], ndata, sigma));
- }
-
- static int checkbit(unsigned int data)
- {
- int bitsum = 0;
- int i;
-
- for (i=0;i<8*sizeof(int);i++) {
- bitsum += data & 01;
- data >>= 1;
- }
- return(bitsum);
- }
-
- static void split(double *comp, double *real, double *ima, int nn)
- {
- int i, j;
- double norm, sqrt(double);
-
- norm = sqrt((double)nn);
- for (i=1,j=1;j<=nn;i+=2,j++) {
- real[j] = comp[i]/norm;
- ima[j] = comp[i+1]/norm;
- }
- return;
- }
-
- static void merge(double *real, double *ima, double *comp, int nn)
- {
- int i, j;
-
- if (ima) {
- for (i=j=1;j<=nn;i+=2,j++) { /* merge, i always odd */
- comp[i] = real[j]; /* real */
- comp[i+1] = ima[j]; /* imaginary */
- }
- }
- else {
- for (i=j=1;j<=nn;i+=2,j++) { /* merge, i always odd */
- comp[i] = real[j]; /* real */
- comp[i+1] = 0.0; /* imaginary */
- }
- }
- return;
- }
-
- #define TWO_PI 6.2831853071795864769252868
-
- static void fft(double *data, int nn, int isign)
- {
- int n, mmax, m, j, istep, i;
- double wtemp, wr, wpr, wpi, wi, theta;
- double rtemp, itemp;
-
- n = nn<<1;
- j = 1;
- for (i=1;i<n;i+=2) {
- if (j > i) {
- rtemp = data[j];
- data[j] = data[i];
- data[i] = rtemp;
- itemp = data[j+1];
- data[j+1] = data[i+1];
- data[i+1] = itemp;
- }
- m = n>>1;
- while (m >= 2 && j > m) {
- j -= m;
- m >>= 1;
- }
- j += m;
- }
- mmax = 2;
- while (n > mmax) {
- istep = mmax<<1;
- theta = TWO_PI/(isign*mmax);
- wtemp = sin(0.5*theta);
- wpr = -2.0*wtemp*wtemp;
- wpi = sin(theta);
- wr = 1.0;
- wi = 0.0;
- for (m=1;m<mmax;m+=2) {
- for (i=m;i<=n;i+=istep) {
- j = i+mmax;
- rtemp = wr*data[j] - wi*data[j+1];
- itemp = wr*data[j+1] + wi*data[j];
- data[j] = data[i]-rtemp;
- data[j+1] = data[i+1]-itemp;
- data[i] += rtemp;
- data[i+1] += itemp;
- }
- wr = (wtemp=wr) * wpr - wi * wpi + wr;
- wi = wi * wpr + wtemp * wpi+ wi;
- }
- mmax = istep;
- }
- return;
- }
-
- static int fftsmooth(double *fromvec, double *smvec, int ndata, float sigma)
- {
- int fmax, num, k, kk, f, last, vecsize=2;
- double yyn, yy1, rn1, fac;
- double *comp;
-
- k = ndata << 1;
- while (vecsize < k)
- vecsize <<= 1;
- ADVECTOR(comp, 1, vecsize, "smooth", return);
- merge(fromvec, NULL, comp, ndata);
- num = vecsize >> 1; /* num = number of complex elements */
- fmax = vecsize >> 2; /* maximum frequency */
- sigma *= fmax;
- sigma *= -sigma;
- last = 2*ndata-1;
- yy1 = comp[1];
- yyn = comp[last];
- rn1 = 1.0/(ndata-1);
- for (kk=f=1;f<=ndata;f++,kk+=2) {
- comp[kk] += (-rn1*(yy1*(ndata-f) + yyn*(f-1)));
- }
- for (f=last+2;f<=vecsize;f++) {
- comp[f] = 0.0; /* zero pad both real and ima */
- }
- fft(comp, num, 1);
- comp[1] /= num; /* normalize: should be real (comp[2] == 0) */
- for (f=1;f<=fmax;f++) {
- k = 2*f+1; /* positive frequencies */
- kk = vecsize-k+2; /* negative frequencies */
- fac = exp(f*f/sigma)/num; /* Gaussian window */
- comp[kk] = (comp[k] *= fac); /* real */
- comp[kk+1] = -(comp[k+1] *= fac); /* ima */
- }
- fft(comp, num, -1);
- for (kk=f=1;f<=ndata;f++,kk+=2) {
- smvec[f] = comp[kk] + (rn1*(yy1*(ndata-f) + yyn*(f-1)));
- }
- return(0);
- }
-